package com.share.cloudStorage.users.service;
import cn.hutool.crypto.digest.DigestUtil;
import cn.hutool.jwt.JWT;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.share.cloudStorage.constant.Constants;
import com.share.cloudStorage.folders.service.FoldersService;
import com.share.cloudStorage.hdfs.HdfsClient;
import com.share.cloudStorage.model.Result;
import com.share.cloudStorage.users.dao.UsersDao;
import com.share.cloudStorage.users.model.Users;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;

import java.io.IOException;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;
import java.util.concurrent.TimeUnit;
@Slf4j
@Service
public class UsersServiceImpl extends ServiceImpl<UsersDao, Users> implements UsersService {

    @Autowired
    private RedisTemplate<String,Object> redisTemplate;

    @Autowired
    private SmsService smsService;

    @Autowired
    private HdfsClient hdfsClient;

    @Autowired
    private UsersDao usersDao;

    @Autowired
    private FoldersService foldersService;
    @Override
    public Result login(Users user, String captchaCode, String captchaId) {
        // 验证码验证
        String storedCode = (String) redisTemplate.opsForValue().get("captcha:" + captchaId);
        if (storedCode == null) {
            return Result.fail("验证码已过期或不存在");
        }

        // 将用户输入的验证码也转换为小写进行比对
        if (!storedCode.equals(captchaCode.toLowerCase())) {
            return Result.fail("验证码错误");
        }
        // 先从缓存拿
        Users cacheUser = (Users) redisTemplate.opsForValue().get("users:" + user.getMobile());
        if (cacheUser != null) {
            if (user.getPassword().equals(cacheUser.getPassword()))
            return createLoginResult(cacheUser);
        }
        // 从数据库拿
        LambdaQueryWrapper<Users> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Users::getMobile, user.getMobile());
        wrapper.eq(Users::getPassword, user.getPassword());
        wrapper.eq(Users::getStatus,1);
        Users dbUser = usersDao.selectOne(wrapper);
        if (dbUser != null) {
            redisTemplate.opsForValue().set("users:" + dbUser.getMobile(), dbUser,1, TimeUnit.HOURS);
            return createLoginResult(dbUser);
        } else {
            return Result.fail("用户或密码错误");
        }
    }

    // 生成 JWT token
    private Result createLoginResult(Users user) {
        String token = JWT.create()
                .setPayload(Constants.USERNAME_KEY, user.getUserId())
                .setPayload("timestamp", System.currentTimeMillis())
                .setKey(Constants.JWT_KEY.getBytes())
                .setExpiresAt(new Date(System.currentTimeMillis() + 3600000))
                .sign();
        redisTemplate.opsForValue().set("tokens:" + user.getUsername(), token);
        Map<String, Object> data = new HashMap<>();
        data.put(Constants.TOKEN_KEY, token);
        data.put("user", user);
        return Result.ok(data);
    }

    //发送手机验证码
    public Result sendCode(Users user){
        String mobile = user.getMobile();
        if (mobile ==null){
            return Result.fail("手机号不能为空");
        }
        String code =String.valueOf(new Random().nextInt(900000) + 100000);
        redisTemplate.opsForValue().set(mobile,code,5,TimeUnit.MINUTES);
        boolean send = smsService.send(mobile, code);
        if (!send){
            return Result.fail("验证码发送失败");
        }
        return Result.ok();
    }




    //手机验证码登录
    public Result logon(Users user, String code) {
        LambdaQueryWrapper<Users> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Users::getMobile,user.getMobile());
        Users dbUser = usersDao.selectOne(wrapper);
        if (dbUser !=null){
            String cacheCode = (String) redisTemplate.opsForValue().get(user.getMobile());
            if (!cacheCode.equals(" ") && cacheCode.equals(code)){
                return createLoginResult(dbUser);
            }
        }
        return Result.fail("登录失败(手机号或验证码错误)");
    }

    //用户注册
    @Override
    @Transactional
    public Result register(Users user, String code) throws IOException {
        try {
            String cacheCode = (String) redisTemplate.opsForValue().get(user.getMobile());
            log.info("Cache code: {}", cacheCode);
            if (cacheCode != null && cacheCode.equals(code)) {
                // 1. 插入用户
                log.info("user:{}",user);
                user.setPassword(DigestUtil.sha256Hex(user.getPassword() + Constants.SALT));
                user.setPhoto("1.jpg");
                usersDao.insert(user);
                log.info("user:{}",user);
                // 2. 插入文件夹记录
                foldersService.save(user);

                // 3. 创建HDFS文件夹

                String filePath= "/"+user.getMobile();
                hdfsClient.createFolder(filePath);

                return Result.ok("注册成功");
            }
            return Result.fail("注册失败(手机号或验证码错误)");
        } catch (Exception e) {
            log.error("注册异常: {}", e.getMessage(), e);
            // 异常发生时，手动回滚数据库操作和HDFS文件夹创建
            // 这里可以根据需要回滚数据库插入和HDFS创建的文件夹操作

            // 手动回滚 HDFS 创建的文件夹
            hdfsClient.deleteFolder(user); // 这里需要在 HdfsClient 中增加删除文件夹的方法

            // 由于 @Transactional 已经会自动回滚数据库操作，这里不需要显式调用回滚
            throw new RuntimeException("注册失败，发生异常", e);
        }
    }


    //获得用户信息
    public Users getUserById(Integer id){
        return usersDao.selectById(id);
    }
    @Override
    public Result updateUserStatus(Users user) {
        LambdaQueryWrapper<Users> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Users::getUserId,user.getUserId());
        //查询回来的user数据
        Users sUser = baseMapper.selectOne(wrapper);
        UpdateWrapper<Users> updateWrapper = new UpdateWrapper<>();
        if (sUser.getStatus()==true){
            updateWrapper.eq("user_id", sUser.getUserId()).set("status", false);
            update(updateWrapper);
        }else {
            updateWrapper.eq("user_id", sUser.getUserId()).set("status", true);
            update(updateWrapper);
        }
        redisTemplate.delete("users:" + user.getMobile());
        return Result.ok("修改成功");
    }
//添加用户
    @Override
    @Transactional
    public String addUser(Users user) {
        try {
            usersDao.insert(user);
            foldersService.save(user);
            hdfsClient.createFolder("/"+user.getMobile());
        } catch (IOException e) {
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            throw new RuntimeException(e);
        }
        return "添加成功";
    }
}